﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HtmlAgilityPack;
using ReaderExtractTool.Service;
using HtmlDocument = HtmlAgilityPack.HtmlDocument;

namespace ReaderExtractTool
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.btnStart.Focus();
            this.btnStart.Select();

            string savePath = AppDomain.CurrentDomain.BaseDirectory + @"downloads\";
            if (!Directory.Exists(savePath))
            {
                Directory.CreateDirectory(savePath);
            }
            this.txtSavePath.Text = savePath;
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            string url = this.txtUrl.Text.Trim();
            if (string.IsNullOrEmpty(url))
            {
                MessageBox.Show(this, "请先填写来源地址！");
                return;
            }
            string savePath = this.txtSavePath.Text.Trim();
            if (string.IsNullOrEmpty(savePath))
            {
                MessageBox.Show(this, "请先选择文件存储目录！");
                return;
            }

            string source = this.comboBox1.Text;

            this.doExecute(source, savePath);            
        }

        /// <summary>
        /// 选择文件存储目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnScan_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            folderBrowserDialog.ShowNewFolderButton = true;
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                this.txtSavePath.Text = folderBrowserDialog.SelectedPath;
            }
        }

        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="url"></param>
        /// <param name="savePath"></param>
        private void doExecute(string source, string savePath)
        {
            Task.Factory.StartNew(() =>
            {
                BaseService ser = null; 

                if (source == "奇奇小说网")
                {
                    ser = new _477ZWService();
                }
                else if (source == "三优小说网")
                {
                    ser = new _3UXiaoShuoService();
                }
                else if (source == "铁书网")
                {
                    ser = new TieShuWangService();
                }

                try
                {
                    string url = this.txtUrl.Text.Trim();

                    this.setWorkStartStyle();

                    // 提取章节目录
                    this.writeTip("正在提取章节目录...");
                    string novelTitle = "";
                    List<Chapter> chapterList = ser.GetChapters(url, ref novelTitle);
                    if (chapterList == null || chapterList.Count == 0)
                    {
                        throw new Exception("未检测到章节目录");
                    }

                    // 提取章节内容
                    List<string> contentList = new List<string>();
                    for (int i = 0; i < chapterList.Count; i++)
                    {
                        this.writeTip($"正在提取章节内容，当前进度：{i + 1}/{chapterList.Count}");
                        contentList.Add(ser.GetChapterContent(chapterList[i], this.txtUnnecessary.Text.Trim()));
                    }
                    if (contentList == null || contentList.Count == 0)
                    {
                        throw new Exception("未提取到任何内容");
                    }

                    // 存储章节内容
                    for (int i = 0; i < contentList.Count; i++)
                    {
                        this.writeTip($"正在保存章节内容，当前进度：{i + 1}/{chapterList.Count}");

                        File.AppendAllText(savePath + @"\" + novelTitle + ".txt", contentList[i]);
                    }

                    this.Invoke(new Action(() =>
                    {
                        MessageBox.Show("数据保存成功");
                    }));

                    this.setWorkEndStyle();
                }
                catch (Exception ex)
                {
                    this.Invoke(new Action(() =>
                    {
                        MessageBox.Show("出错啦：" + ex.Message);

                        this.setWorkEndStyle();
                    }));
                }
            });
        }

        /// <summary>
        /// 记录提示信息
        /// </summary>
        /// <param name="text"></param>
        private void writeTip(string text)
        {
            this.Invoke(new Action(() =>
            {
                this.lbTip.Text = text;
            }));
        }

        /// <summary>
        /// 设置任务开始时的样式
        /// </summary>
        private void setWorkStartStyle()
        {
            this.Invoke(new Action(() =>
            {
                this.lbTip.Visible = true;
                this.lbTip.Text = "正在提取章节目录...";
                this.txtUrl.ReadOnly = true;
                this.btnStart.Enabled = false;
            }));
        }

        /// <summary>
        /// 设置任务结束时的样式
        /// </summary>
        private void setWorkEndStyle()
        {
            this.Invoke(new Action(() =>
            {
                this.lbTip.Visible = false;
                this.btnStart.Enabled = true;
                this.txtUrl.ReadOnly = false;
            }));
        }

        /// <summary>
        /// 提取章节目录
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private List<Chapter> getChapters(string url, ref string title)
        {
            List<Chapter> chapterList = new List<Chapter>();

            var doc = new HtmlWeb().Load(url);
            var node = doc.DocumentNode;
            var result = node.SelectNodes(".//div[@id='list']/dl");
            if (result == null || result.Count == 0) throw new Exception("未检测到章节目录");

            // 提取所有章节目录
            foreach (var r in result)
            {
                if (string.IsNullOrEmpty(r.InnerHtml)) continue;

                var titleNode = r.ChildNodes.FirstOrDefault(f => f.Name == "dt");
                title = titleNode.InnerText.Replace("《", "").Replace("》", "").Replace(" ", "").Replace("正文", "");

                var chapterNodes = r.ChildNodes.Where(w => w.Name == "dd");
                if (chapterNodes == null || chapterNodes.Count() == 0) continue;
                foreach (var chapterNode in chapterNodes)
                {
                    string chapterName = chapterNode.InnerText;
                    string chapterLink = chapterNode.ChildNodes[0].Attributes["href"].Value;
                    chapterList.Add(new Chapter()
                    {
                        name = chapterName,
                        link = url + chapterLink.Split('/').LastOrDefault()
                    });
                }
            }

            return chapterList;
        }

        /// <summary>
        /// 提取章节内容
        /// </summary>
        /// <param name="chapterList"></param>
        /// <returns></returns>
        private List<string> getChapterContent(List<Chapter> chapterList)
        {
            List<string> contentList = new List<string>();

            for (int i = 0; i < chapterList.Count; i++)
            {
                this.Invoke(new Action(() =>
                {
                    this.lbTip.Text = $"正在提取章节内容，当前进度：{i + 1}/{chapterList.Count}";
                }));

                var doc = new HtmlWeb().Load(chapterList[i].link);
                var node = doc.DocumentNode;
                var result = node.SelectNodes(".//div[@id='content']");
                string content = result[0].InnerHtml.Replace("<br>", "\r\n");

                if(this.checkBox1.Checked && !string.IsNullOrEmpty(this.txtUnnecessary.Text.Trim()))
                { 
                    int index = content.IndexOf(this.txtUnnecessary.Text.Trim());
                    content = content.Substring(0, index);
                }
                contentList.Add(chapterList[i].name + "\r\n" + content + "\r\n\r\n");
            }

            return contentList;
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (this.checkBox1.Checked)
            {
                this.lbUnnecessary.Visible = true;
                this.txtUnnecessary.Visible = true;
                this.lbTip.Location = new Point(155, 252);
                this.btnStart.Location = new Point(257, 282);
                this.Height = 392;
            }
            else
            {
                this.lbUnnecessary.Visible = false;
                this.txtUnnecessary.Visible = false;
                this.txtUnnecessary.Text = "";
                this.lbTip.Location = new Point(155, this.checkBox1.Location.Y + this.checkBox1.Height + 20);
                this.btnStart.Location = new Point(257, 240);
                this.Height = 350;
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.comboBox1.Text == "奇奇小说网")
            {
                this.txtUrl.Text = "https://www.477zw.com/";
            }
            else if (this.comboBox1.Text == "三优小说网")
            {
                this.txtUrl.Text = "https://www.3uxiaoshuo.com/xiaoshuo/";
            }
            else if (this.comboBox1.Text == "铁书网")
            {
                this.txtUrl.Text = "https://www.tiesw.la/1_1355/";
            }
        }
    }
}
